#pragma once

#include <iostream>
#include <stdarg.h>

#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4
#define SIZE 1024

#define Log_Name "log.txt"
#define Screen 1
#define OneFile 2
#define ClassFile 3

class Log
{
public:
    Log()
    {
        printmethod = Screen;
        logpath = "./log/";
    }

    void Enable(int method)
    {
        printmethod = method;
    }

    std::string levelToString(int level)
    {
        switch (level)
        {
        case Info:
            return "Info";
        case Debug:
            return "Debug";
        case Warning:
            return "Warning";
        case Error:
            return "Error";
        case Fatal:
            return "Fatla";
        default:
            return "None";
        }
    }

    // void logmessage(int level, const char *format, ...)
    // {
    //     char leftbuffer[SIZE];
    //     time_t t = time(nullptr);
    //     struct tm *ctime = localtime(&t);
    //     snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
    //              ctime->tm_year, ctime->tm_mon, ctime->tm_mday,
    //              ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

    //     // printf("%s\n",leftbuffer);

    //     char rightbuffer[SIZE];
    //     va_list s;
    //     va_start(s, format);
    //     vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
    //     va_end(s);

    //     // printf("%s\n",rightbuffer);

    //     // 格式：默认格式+自定义格式
    //     char logtxt[SIZE * 2];
    //     snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);

    //     // printf("%s", logtxt);
    //     printLog(level, logtxt);
    // }

    void printLog(int level, const std::string &logtxt)
    {
        switch (printmethod)
        {
        case Screen:
            std::cout << logtxt << std::endl;
            break;
        case OneFile:
            printOneFile(Log_Name, logtxt);
            break;
        case ClassFile:
            printClassFile(level, logtxt);
            break;
        default:
            break;
        }
    }

    void printOneFile(const std::string &logname, const std::string &logtxt)
    {
        std::string _logname = logpath + logname;
        int fd = open(_logname.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0666);
        if (fd < 0)
            return;
        write(fd, logtxt.c_str(), logtxt.size());

        close(fd);
    }

    void printClassFile(int level, const std::string &logtxt)
    {
        std::string filename = Log_Name;
        filename += '.';
        filename += levelToString(level);
        printOneFile(filename, logtxt);
    }

    void operator()(int level, const char *format, ...)
    {
        char leftbuffer[SIZE];
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
                 ctime->tm_year, ctime->tm_mon, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        // printf("%s\n",leftbuffer);

        char rightbuffer[SIZE];
        va_list s;
        va_start(s, format);
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        // printf("%s\n",rightbuffer);

        // 格式：默认格式+自定义格式
        char logtxt[SIZE * 2];
        snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);

        // printf("%s", logtxt);
        printLog(level, logtxt);
    }
    ~Log()
    {
    }

private:
    int printmethod;
    std::string logpath;
};

// int sum(int n, ...)
// {
//     va_list s; // char*
//     va_start(s, n);
//     int sum = 0;
//     while (n)
//     {
//         //std::cout<<va_arg(s, int)<<" ";
//         sum+=va_arg(s,int);
//         n--;
//     }

//     va_end(s); //s==nullptr
//     return sum;
// }